/**
 * 数据导出工具
 * 支持 Excel 和 CSV 格式导出
 * 兼容 ConfigurableTable 组件的 columns 配置
 * 默认导出数据文字居中对齐
 */

import * as XLSX from 'xlsx-js-style'
import { saveAs } from 'file-saver'

/**
 * 导出为 Excel 文件
 * @param {Array} data - 数据数组，每个元素是一个对象
 * @param {Array} columns - 列配置数组，格式：[{ label: '列名', key: '字段名', width: 20, format: (value) => value }]
 * @param {String} filename - 文件名（不含扩展名）
 * @param {String} sheetName - 工作表名称，默认为 '数据'
 * @param {Object} options - 其他选项
 *   @param {Boolean} options.textColumns - 需要设置为文本格式的列索引数组，如 [0, 2] 表示第1列和第3列
 */
export function exportToExcel(data, columns, filename, sheetName = '数据', options = {}) {
  try {
    // 1. 构建表头
    const headers = columns.map(col => col.label)

    // 2. 构建数据行
    const rows = data.map(item => {
      return columns.map(col => {
        let value = item[col.key]

        // 如果有自定义格式化函数，使用它
        if (col.format && typeof col.format === 'function') {
          value = col.format(value, item)
        }

        return value !== undefined && value !== null ? value : ''
      })
    })

    // 3. 合并表头和数据
    const wsData = [headers, ...rows]

    // 4. 创建工作表
    const ws = XLSX.utils.aoa_to_sheet(wsData)

    // 5. 设置列宽
    if (columns.some(col => col.width)) {
      ws['!cols'] = columns.map(col => ({ wch: col.width || 15 }))
    }

    // 6. 设置所有单元格默认居中对齐
    const range = XLSX.utils.decode_range(ws['!ref'])
    for (let row = range.s.r; row <= range.e.r; row++) {
      for (let col = range.s.c; col <= range.e.c; col++) {
        const cellAddress = XLSX.utils.encode_cell({ r: row, c: col })
        if (ws[cellAddress]) {
          // 设置单元格样式
          ws[cellAddress].s = {
            alignment: {
              horizontal: 'center', // 水平居中
              vertical: 'center'    // 垂直居中
            },
            font: {
              // 表头加粗
              bold: row === 0
            }
          }
        }
      }
    }

    // 7. 将指定列设置为文本格式（防止长数字显示为科学计数法）
    const textColumns = options.textColumns || []
    if (textColumns.length > 0) {
      for (let row = 1; row <= range.e.r; row++) {
        textColumns.forEach(colIndex => {
          const cellAddress = XLSX.utils.encode_cell({ r: row, c: colIndex })
          if (ws[cellAddress]) {
            ws[cellAddress].t = 's' // 设置为字符串类型
            ws[cellAddress].v = String(ws[cellAddress].v)
            // 保持居中样式
            if (!ws[cellAddress].s) {
              ws[cellAddress].s = {}
            }
            if (!ws[cellAddress].s.alignment) {
              ws[cellAddress].s.alignment = {}
            }
            ws[cellAddress].s.alignment.horizontal = 'center'
            ws[cellAddress].s.alignment.vertical = 'center'
          }
        })
      }
    }

    // 8. 创建工作簿
    const wb = XLSX.utils.book_new()
    XLSX.utils.book_append_sheet(wb, ws, sheetName)

    // 9. 生成Excel文件
    const wbout = XLSX.write(wb, { bookType: 'xlsx', type: 'array' })

    // 10. 下载文件
    const blob = new Blob([wbout], { type: 'application/octet-stream' })
    saveAs(blob, `${filename}.xlsx`)

    return true
  } catch (error) {
    console.error('Excel导出失败:', error)
    throw new Error('Excel导出失败: ' + error.message)
  }
}

/**
 * 导出为 CSV 文件
 * @param {Array} data - 数据数组，每个元素是一个对象
 * @param {Array} columns - 列配置数组，格式：[{ label: '列名', key: '字段名', format: (value) => value }]
 * @param {String} filename - 文件名（不含扩展名）
 * @param {Object} options - 其他选项
 *   @param {String} options.separator - 分隔符，默认为逗号
 *   @param {Boolean} options.withBOM - 是否添加 BOM（解决 Excel 打开中文乱码），默认为 true
 */
export function exportToCSV(data, columns, filename, options = {}) {
  try {
    const separator = options.separator || ','
    const withBOM = options.withBOM !== false

    // 1. 构建表头
    const headers = columns.map(col => col.label).join(separator)

    // 2. 构建数据行
    const rows = data.map(item => {
      return columns.map(col => {
        let value = item[col.key]

        // 如果有自定义格式化函数，使用它
        if (col.format && typeof col.format === 'function') {
          value = col.format(value, item)
        }

        // 处理空值
        if (value === undefined || value === null) {
          return ''
        }

        // 转换为字符串
        value = String(value)

        // 如果值中包含分隔符、双引号或换行符，需要用双引号包裹，并转义双引号
        if (value.includes(separator) || value.includes('"') || value.includes('\n')) {
          value = '"' + value.replace(/"/g, '""') + '"'
        }

        return value
      }).join(separator)
    })

    // 3. 合并表头和数据
    const csvContent = [headers, ...rows].join('\n')

    // 4. 创建 Blob（添加 BOM 以支持 Excel 正确识别中文）
    const BOM = '\uFEFF'
    const blob = new Blob(
      [withBOM ? BOM + csvContent : csvContent],
      { type: 'text/csv;charset=utf-8;' }
    )

    // 5. 下载文件
    saveAs(blob, `${filename}.csv`)

    return true
  } catch (error) {
    console.error('CSV导出失败:', error)
    throw new Error('CSV导出失败: ' + error.message)
  }
}

/**
 * 通用导出函数（根据类型自动选择导出方式）
 * @param {String} type - 导出类型：'excel' 或 'csv'
 * @param {Array} data - 数据数组
 * @param {Array} columns - 列配置数组
 * @param {String} filename - 文件名
 * @param {Object} options - 其他选项
 */
export function exportData(type, data, columns, filename, options = {}) {
  if (!data || !data.length) {
    throw new Error('没有可导出的数据')
  }

  if (!columns || !columns.length) {
    throw new Error('列配置不能为空')
  }

  if (!filename) {
    filename = `导出数据_${formatDate(new Date())}`
  }

  const lowerType = type.toLowerCase()

  if (lowerType === 'excel' || lowerType === 'xlsx') {
    return exportToExcel(data, columns, filename, options.sheetName, options)
  } else if (lowerType === 'csv') {
    return exportToCSV(data, columns, filename, options)
  } else {
    throw new Error(`不支持的导出类型: ${type}`)
  }
}

/**
 * 将 ConfigurableTable 的 columns 配置转换为导出用的 columns 配置
 * @param {Array} tableColumns - ConfigurableTable 的 columns 配置
 * @param {Object} formatters - 自定义格式化函数映射（可选），用于需要访问 this 或自定义逻辑的列
 *   格式：{ prop名: (value, row) => 格式化后的值 }
 * @param {Object} options - 其他选项
 *   @param {Array} options.excludeProps - 要排除的列的 prop 名称数组（如操作列）
 *   @param {Object} options.labelOverrides - 自定义表头文字映射，用于导出时使用不同的表头文字
 * @returns {Array} 导出用的 columns 配置
 *
 * @example
 * // 基础用法
 * const exportColumns = convertTableColumnsToExport(this.tableColumns)
 *
 * @example
 * // 排除操作列并自定义格式化
 * const exportColumns = convertTableColumnsToExport(
 *   this.tableColumns,
 *   {
 *     statue: (value) => this.getStatusText(value), // 状态转文字
 *     amount: (value) => formatAmount(value) // 金额格式化
 *   },
 *   {
 *     excludeProps: ['actions'], // 排除操作列
 *     labelOverrides: {
 *       statue: '状态' // 将"订单状态"改为"状态"
 *     }
 *   }
 * )
 */
export function convertTableColumnsToExport(tableColumns, formatters = {}, options = {}) {
  const { excludeProps = [], labelOverrides = {} } = options

  return tableColumns
    .filter(col => {
      // 排除没有 prop 的列（如操作列）
      if (!col.prop) return false
      // 排除指定要排除的列
      if (excludeProps.includes(col.prop)) return false
      // 排除有 slot 但没有提供 formatter 的列
      if (col.slot && !formatters[col.prop] && !col.formatter) return false
      return true
    })
    .map(col => {
      const exportCol = {
        label: labelOverrides[col.prop] || col.label,
        key: col.prop,
        width: col.width ? Math.ceil(col.width / 8) : 15 // 将像素宽度转换为 Excel 字符宽度（粗略估算）
      }

      // 处理格式化函数的优先级：
      // 1. formatters 参数中提供的格式化函数（最高优先级）
      // 2. tableColumns 中的 formatter 函数
      if (formatters[col.prop]) {
        exportCol.format = formatters[col.prop]
      } else if (col.formatter && typeof col.formatter === 'function') {
        // 将 Element UI 的 formatter(row, column, cellValue, index) 转换为导出用的 format(value, row)
        exportCol.format = (value, row) => col.formatter(row, null, value, null)
      }

      return exportCol
    })
}

/**
 * 格式化日期为 YYYY-MM-DD 格式
 * @param {Date} date - 日期对象
 * @returns {String}
 */
function formatDate(date) {
  const year = date.getFullYear()
  const month = String(date.getMonth() + 1).padStart(2, '0')
  const day = String(date.getDate()).padStart(2, '0')
  return `${year}-${month}-${day}`
}

/**
 * 格式化日期时间为 YYYY-MM-DD HH:mm:ss 格式
 * @param {Date} date - 日期对象
 * @returns {String}
 */
export function formatDateTime(date) {
  if (!date) return ''
  if (typeof date === 'string') {
    date = new Date(date)
  }

  const year = date.getFullYear()
  const month = String(date.getMonth() + 1).padStart(2, '0')
  const day = String(date.getDate()).padStart(2, '0')
  const hours = String(date.getHours()).padStart(2, '0')
  const minutes = String(date.getMinutes()).padStart(2, '0')
  const seconds = String(date.getSeconds()).padStart(2, '0')

  return `${year}-${month}-${day} ${hours}:${minutes}:${seconds}`
}

/**
 * 金额格式化（分转元，保留两位小数）
 * @param {Number} amount - 金额（单位：分）
 * @returns {String}
 */
export function formatAmount(amount) {
  if (amount === undefined || amount === null) return '0.00'
  return (amount / 100).toFixed(2)
}

export default {
  exportToExcel,
  exportToCSV,
  exportData,
  convertTableColumnsToExport,
  formatDateTime,
  formatAmount
}

